﻿using System;
using System.Configuration;
using System.Text.RegularExpressions;
using System.IO;
using System.Xml;
using System.Data;
using System.Collections.Generic;

namespace AspCompiler
{
    public static class Config
    {
        /// <summary>
        /// The path to the asp.net compiler utility.
        /// </summary>
        public static string Compiler(string path)
        {
            return ProcessEnvironmentPaths(GetSetting(path, "compiler"));
        }

        /// <summary>
        /// The path to the asp.net merge utility.
        /// </summary>
        public static string Merge(string path)
        {
            return ProcessEnvironmentPaths(GetSetting(path, "merge"));
        }

        /// <summary>
        /// The compiler utility arguments to use when compiling a website.
        /// </summary>
        public static string CompilerArgs(string path)
        {
            return GetSetting(path, "compiler-args");
        }

        /// <summary>
        /// The merge utility arguments to use when merging the assemblies of a compiled website.
        /// </summary>
        public static string MergeArgs(string path)
        {
            return GetSetting(path, "merge-args");
        }

        /// <summary>
        /// The web root paths containing the development websites.
        /// </summary>
        public static string[] WebRoot
        {
            get
            {
                List<string> res = new List<string>();
                foreach (string val in ConfigurationManager.AppSettings["webroot"].Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
                    res.Add(EnsureTrailingSlash(ProcessEnvironmentPaths(val)));
                return res.ToArray();
            }
        }

        /// <summary>
        /// The path to publish the compiled website to.
        /// </summary>
        public static string PubRoot
        {
            get
            {
                var res = ProcessEnvironmentPaths(ConfigurationManager.AppSettings["pubroot"]);
                return EnsureTrailingSlash(res);
            }
        }

        /// <summary>
        /// Resolves %WINDIR% in the path to C:\Windows
        /// </summary>
        private static string ProcessEnvironmentPaths(string path)
        {
            return Regex.Replace(path ?? "", "%.*%", delegate(Match m) { return Environment.GetEnvironmentVariable(m.Value.Substring(1, m.Value.Length - 2)); });
        }

        /// <summary>
        /// Ensures that the path ends with a '\'
        /// </summary>
        private static string EnsureTrailingSlash(string path)
        {
            return path.EndsWith("\\") ? path : path + "\\";
        }

        private static string GetSetting(string path, string name)
        {
            string targetFramework = null;

            if (File.Exists(path + "web.config"))
            {
                DataSet ds = new DataSet();
                ds.ReadXml(path + "web.config");
                if (ds.Tables.Contains("compilation") && ds.Tables["compilation"].Columns.Contains("targetFramework"))
                    targetFramework = ds.Tables["compilation"].Rows[0]["targetFramework"] as string;
            }

            if (File.Exists(path + "compiler.config"))
            {
                try
                {
                    DataSet config = new DataSet();
                    config.ReadXml(path + "compiler.config");
                    DataRow setting = null;
                    foreach (DataRow row in config.Tables["add"].Rows)
                        if (targetFramework != null && row["key"] as string == targetFramework + "_" + name || setting == null && row["key"] as string == name)
                            setting = row;
                    return setting["value"].ToString();
                }
                catch (Exception) { }
            }

            if (targetFramework != null && ConfigurationManager.AppSettings[targetFramework + "_" + name] != null)
                return ConfigurationManager.AppSettings[targetFramework + "_" + name];

            return ConfigurationManager.AppSettings[name];
        }
    }
}
